package com.jt.interceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import com.alibaba.druid.util.StringUtils;
import com.jt.pojo.User;
import com.jt.util.ObjectMapperUtil;
import com.jt.util.UserThreadLocal;

import redis.clients.jedis.JedisCluster;

/**
 * 定义用户拦截器，实现用户权限判断
 * spring版本4 必须重写所有方法
 * spring版本5 不用重写所有方法，需要哪个就重写哪个
 */
@Component
public class UserInterceptor implements HandlerInterceptor {
	
	@Autowired
	private JedisCluster jedisCluster;
	
	/**
	 * 重写preHandle方法实现用户登录校验
	 * boolean:
	 * 	true:请求方行
	 * 	false:请求拦截，且一般有重定向执行
	 * 用户登录校验的业务实现：
	 * 1.判断用户时候登录cookie("JT_TICKET",ticket)
	 * 2.检查redis中是否有数据
	 * 3.return true
	 * 
	 * 问题：拦截器中的user对象如何传给下层Controller，让其动态获取用户id？
	 * 方式一：利用request对象（初级程序员，在拦截器中设置值，在Controller中取值，每个controller都要写相同代码）
	 * 方式二：在拦截器中利用ThreadLocal本地线程对象绑定user，后续该线程的任何环节都可以使用
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		//获取用户登录信息
		Cookie[] cookies = request.getCookies();
		String ticket=null;
		if (cookies.length>0) {
			for (Cookie cookie : cookies) {
				if ("JT_TICKET".equals(cookie.getName())) {
					ticket=cookie.getValue();
					break;
				}
			}
		}
		
		//判断ticket取值是否为空，不为null时校验redis中是否有数据
		if (!StringUtils.isEmpty(ticket)) {
			String userJSON = jedisCluster.get(ticket);
			if (!StringUtils.isEmpty(userJSON)) {
				User user = ObjectMapperUtil.toObject(userJSON, User.class);
				UserThreadLocal.set(user);//把当前获取到的用户登录数据绑定到当前线程
				return true;//redis中有数据表示用户已经登录，放行请求
			}
		}
		
		//重定向到登录页面
		response.sendRedirect("/user/login.html");
		return false;//拦截请求
	}
	
	/**
	 * 删除ThreadLocal防止内存泄漏
	 */
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		UserThreadLocal.remove();
	}
}
